/*
Package middle 中间件
*/
package middle

import (
	"net/http"
	"pegasus/datatypes"
	"pegasus/services"
	"pegasus/utils"
	"reflect"
	"strings"

	"github.com/dalixu/ginjector"

	"github.com/dalixu/owig"
)

//CheckSession session检测 过滤掉session不合法的请求
//由于没分开登录服务器和业务服务器 需要对auth请求放开
type CheckSession struct {
	ignores []string
}

//NewCheckSession 返回checkSession
func NewCheckSession(ignores ...string) *CheckSession {
	return &CheckSession{
		ignores: ignores,
	}
}

//Invoke 中间件的实现
func (cs *CheckSession) Invoke(ctx owig.Context) {
	req := ctx.Request()
	contains := false
	for _, v := range cs.ignores {
		if strings.Contains(req.URL.Path, v) {
			contains = true
		}
	}
	if !contains {
		token := req.Header.Get(utils.Authorization)
		if token == "" {
			//websocket 通常授权不能放到Header里只能放到QueryString中
			req.ParseForm()
			token = req.Form.Get(utils.Authorization)
		}
		//不在ignore列表中
		//非登录请求那么需要验证session 验证通过的话调用添加UserContext的注入
		if token == "" {
			ctx.Response().WriteResult(http.StatusUnauthorized, []byte("未登录"))
			return
		}
		sm := ctx.Container().MustResolve(reflect.TypeOf((*services.SessionService)(nil)).Elem()).Interface().(services.SessionService)
		if sm == nil {
			ctx.Response().WriteResult(http.StatusUnauthorized, []byte("找不到登录服务器"))
			return
		}
		//验证
		si := sm.Update(token)
		if si == nil {
			ctx.Response().WriteResult(http.StatusUnauthorized, []byte("登录失效"))
			return

		}
		builder := ginjector.New()
		builder.Register(func(c ginjector.Container) interface{} { return si }).As(reflect.TypeOf((*datatypes.SIContent)(nil)).Elem())
		ctx.UpdateContainer(builder.Build(ctx.Container()))
		//不在ignore列表中 在回复的header里添加访问的token
		ctx.Response().Header().Add(utils.Authorization, token)
	}
	ctx.Next()
}
